/**
 * 继承和多态
 * 1.继承
 * 2.多态
 */

/**
 * 大纲
 *      大纲分点
 *          分点
 *              分点详写
 */
class Animal {
    public String name;
    public int age;

    static {
        System.out.println("父类静态代码块");
    }

    {
        System.out.println("父类实例代码块");
    }
    public Animal(String name,int age) {
        this.name = name;
        this.age = age;

        System.out.println("父类构造方法");
    }
    public void eat() {
        System.out.println(this.name + "正在吃...");
    }
}

class Dog extends Animal {
    private String color;

    static {
        System.out.println("子类静态代码块");
    }

    {
        System.out.println("子类实例代码块");
    }

    public Dog(String name,int age,String color) {
        super(name,age);
        this.color = color;

        System.out.println("子类构造方法");
    }
    public void barks() {
        System.out.println(this.name + "正在汪汪叫~~");
    }
}

class Cat extends Animal {

    public Cat() {
        super("咪咪",4);
    }
    public void barks() {
        System.out.println(this.name + "正在喵喵叫....");
    }
}
public class Test {
    /**
     * 多态->demo3多态进行演示
     *
     * @param args
     */
    public static void main(String[] args) {

    }
    /**
     * 继承(共类的抽取,实现代码复用)
     * @param args
     * 1.为什么需要继承
     *      实体之间存在一定的联系,通过对共性的抽取,就可以实现代码复用
     * 2.继承的概念
     *      使代码可以复用的重要手段,允许在原本类特性上,再次进行拓展,增加新功能.
     *      产生的类为派生类/子类,被继承的类称为基类/父类/超类
     *      主要解决问题:对共性的抽取,实现代码复用
     * 3.继承的语法
     *      修饰符 class 子类 extends 父类 { 子类成员变量 子类成员方法}
     *      注:1.子类会将父类中的所有成员继承到子类中
     *      2.子类中需要有自己的成员变量/方法,否则就没有继承的意义
     *  4.父类成员访问->Test2演示
     *  5.super关键字,在子类方法中,访问父类的成员
     *      注: 1.不能在static中使用super关键字,因为static不依赖对象
     *          2.只能在子类方法中访问父类的成员
     *  6.子类构造方法->子类成员由父类成员和子类新增成员组成,先有父后有子,所以进行实例化时,编译器会先调用父类构造方法对父类进行初始化
     *  7.this关键字与super关键字的区别
     *  8.再谈初始化
     *  9.protected关键字 相同包的相同类 不同类 不同包的子类 ->demo1 demo2进行演示
     *  10.继承方式:单继承(猫继承动物) 多层继承(田园猫继承猫,猫继承动物) 多个类继承一个类(狗继承动物,猫继承动物) 多继承(JAVA不支持)
     *      一般我们希望继承不超过三层,如果超过,就要考虑代码重构
     *  11.final关键字:用来修饰成员变量 成员方法 类 ->FinalTest类进行演示
     *  12.继承和组合->组合只是一种表达类之间的关系,可以达到代码复用效果,不含特殊语法->TestPart演示
     */

    /**
     * protected关键字
     * @param args
     */
    public static void main5(String[] args) {

    }
    /**
     * 再谈初始化
     * @param args
     *      第一次执行:父类静态 子类静态 父类实例 父类构造 子类实例 子类构造
     *      第二次执行:父类实例 父类构造 子类实例 子类构造
     *      注:1.静态代码块先执行,且只执行一次,进行类加载时执行
     *      2.只有进行实例化时,才会调用实例代码块,然后再调用构造方法
     */
    public static void main4(String[] args) {
        Dog dog1 = new Dog("小黑",1,"黑色");

        System.out.println("==================");

        Dog dog2 = new Dog("小灰",2,"灰毛");
    }
    public static void main3(String[] args) {
        /**
         * this关键字与super关键字的区别
         *  1.相同点
         *      1.都是JAVA关键字
         *      2.都必须在非静态方法中使用
         *      3.访问构造方法时,super,this都必须在第一行
         *  2.不同点
         *      1.this是访问子类成员变量,成员方法,成员构造方法.super是访问父类成员变量,成员方法,成员构造方法
         *      2.this()不写时,编译器不会自动添加,super()不写时,编译器会自动添加
         *      3.this访问变量和方法不存在时,会访问父类成员变量和方法,super只访问父类的,不存在则编译报错
         */
    }
    /**
     * 子类构造方法
     * @param args
     *  1.当父类中没有构造方法时,编译器会给予一个默认构造方法
     *  2.如果父类构造方法带参数,那么需要用户为子类显示定义构造方法,而且必须选择合适的构造方法对父类进行初始化,否则编译错误
     *  3.super构造方法只能出现在子类构造方法中一次,super()构造方法与this()构造方法不能同时出现,因为两者都需要放到第一行
     */
    public static void main2(String[] args) {
        Dog dog = new Dog("小黑",12,"黑色");

        Cat cat = new Cat();
    }
//    public static void main1(String[] args) {
//        Dog dog = new Dog();
//        dog.name = "小黑";
//        dog.eat();
//        dog.barks();
//
//        Cat cat = new Cat();
//        cat.name = "大咪咪";
//        cat.eat();
//        cat.barks();
//    }
}
